package com.baidu.elinkagescroll.sample;

import com.baidu.elinkagescroll.*;
import com.baidu.elinkagescroll.view.NestedFrameLayout;

import com.ryan.ohos.extension.EstimateHelper;

import ohos.agp.components.*;
import ohos.app.Context;

/**
 * LFrameLayout
 *
 * @since 2021/7/15
 */
public class LFrameLayout extends NestedFrameLayout implements ILinkageScroll, ComponentContainer.ArrangeListener, Component.EstimateSizeListener {
    private ChildLinkageEvent mLinkageEvent;
    private ListContainer mRecyclerView;

    /**
     * init LFrameLayout
     *
     * @param context context
     */
    public LFrameLayout(Context context) {
        this(context, null);
    }

    /**
     * init LFrameLayout
     *
     * @param context context
     * @param attrSet attrSet
     */
    public LFrameLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * init LFrameLayout
     *
     * @param context context
     * @param attrSet attrSet
     * @param styleName styleName
     */
    public LFrameLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setEstimateSizeListener(this);
        setArrangeListener(this);
        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                mRecyclerView = (ListContainer) getComponentAt(0);
                mRecyclerView.setScrolledListener(new ScrolledListener() {
                    @Override
                    public void onContentScrolled(Component component,
                                                  int scrollX,
                                                  int scrollY,
                                                  int oldScrollX,
                                                  int oldScrollY) {
                        if (!mRecyclerView.canScroll(DRAG_UP)) {
                            if (mLinkageEvent != null) {
                                mLinkageEvent.onContentScrollToTop(LFrameLayout.this);
                            }
                        }

                        if (!mRecyclerView.canScroll(DRAG_DOWN)) {
                            if (mLinkageEvent != null) {
                                mLinkageEvent.onContentScrollToBottom(LFrameLayout.this);
                            }
                        }

                        if (mLinkageEvent != null) {
                            mLinkageEvent.onContentScroll(LFrameLayout.this);
                        }
                    }
                });
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });
    }

    @Override
    public boolean onEstimateSize(int widthSpecConfig, int heightSpecConfig) {
        int size = getChildCount();
        int height = 0;
        for (int i = 0; i < size; i++) {
            Component child = getComponentAt(i);
            if (child instanceof ListContainer) {
                ListContainer container = (ListContainer) child;
                Component listItem = container.getItemProvider().getComponent(0, null, container);
                measureChild(listItem, widthSpecConfig, heightSpecConfig);
                int itemHeight = listItem.getEstimatedHeight();
                int listHeight = itemHeight * container.getChildCount();
                final ComponentContainer.LayoutConfig lp = child.getLayoutConfig();
                final int childWidthMeasureSpec = EstimateHelper.getChildMeasureSpec(widthSpecConfig,
                        getPaddingLeft() + getPaddingRight(), lp.width);
                final int childHeightMeasureSpec = EstimateHelper.getChildMeasureSpec(heightSpecConfig,
                        getPaddingTop() + getPaddingBottom(), listHeight);
                container.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
                height = Math.max(height, listHeight);
            } else {
                height = Math.max(height, EstimateSpec.getSize(heightSpecConfig));
                measureChild(child, widthSpecConfig, heightSpecConfig);
            }
        }
        setEstimatedSize(EstimateSpec.getSize(widthSpecConfig), height);
        return true;
    }

    private void measureChild(Component child, int parentWidthMeasureSpec,
                                int parentHeightMeasureSpec) {
        final ComponentContainer.LayoutConfig lp = child.getLayoutConfig();

        final int childWidthMeasureSpec = EstimateHelper.getChildMeasureSpec(parentWidthMeasureSpec,
                getPaddingLeft() + getPaddingRight(), lp.width);
        final int childHeightMeasureSpec = EstimateHelper.getChildMeasureSpec(parentHeightMeasureSpec,
                getPaddingTop() + getPaddingBottom(), lp.height);
        child.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
    }

    @Override
    public boolean onArrange(int left, int top, int right, int bottom) {
        int childTop = top;
        int childHeight = 0;
        int size = getChildCount();
        for (int i = 0; i < size; i++) {
            Component child = getComponentAt(i);
            int childBottom = childTop + child.getEstimatedHeight();
            childHeight = Math.max(childHeight, child.getEstimatedHeight());
            child.arrange(left, childTop, right, child.getEstimatedHeight());
        }
        return true;
    }

    @Override
    public void setChildLinkageEvent(ChildLinkageEvent event) {
        mLinkageEvent = event;
    }

    @Override
    public LinkageScrollHandler provideScrollHandler() {
        return new LinkageScrollHandler() {
            @Override
            public void flingContent(Component target, int velocityY) {
            }

            @Override
            public void scrollContentToTop() {
                mRecyclerView.scrollTo(0);
            }

            @Override
            public void scrollContentToBottom() {
                BaseItemProvider adapter = mRecyclerView.getItemProvider();
                if (adapter != null && adapter.getCount() > 0) {
                    mRecyclerView.scrollTo(adapter.getCount() - 1);
                }
            }

            @Override
            public void stopContentScroll(Component target) {
            }

            @Override
            public boolean canScrollVertically(int direction) {
                return mRecyclerView.canScroll(direction);
            }

            @Override
            public boolean isScrollable() {
                return true;
            }

            @Override
            public int getVerticalScrollExtent() {
                return getScrollValue(Component.AXIS_Y);
            }

            @Override
            public int getVerticalScrollOffset() {
                return getScrollbarFadingDelay();
            }

            @Override
            public int getVerticalScrollRange() {
                return getScrollValue(Component.AXIS_Y);
            }
        };
    }
}
